/**
 * @file    ble_gatts.c
 * @author  Azolla (1228449928@qq.com)
 * @brief   ble gatt server
 * @version 0.1
 * @date    2022-11-03
 * 
 * @copyright Copyright (c) 2023
 * */

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "freertos/queue.h"  
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
 
#include "ble_gap.h"

#define TAG "BLE_GAP"
//===================================================================================================================
//===================================================================================================================
#if CONFIG_BLE_MESH_ENABLE /* BLE-MESH */
static ble_mesh_gap_callback_t ble_mesh_gap_callback[BLE_GATT_MAX_ROLE] = { NULL };
void ble_mesh_gap_register_callback(ble_mesh_gap_callback_t cb, ble_gatt_role_t event)
{
    if (cb) {
        ble_mesh_gap_callback[event] = cb;
    }
}

void ble_mesh_gap_unregister_callback(ble_gatt_role_t event)
{
    ble_mesh_gap_callback[event] = NULL;
}

static void ble_mesh_event_callback(esp_ble_mesh_ble_cb_event_t event, esp_ble_mesh_ble_cb_param_t *param)
{
    for (uint8_t i = 0; i < BLE_GATT_MAX_ROLE; i++) {
        if (ble_mesh_gap_callback[i])  {
            ble_mesh_gap_callback[i](event, param);
        }
    }
}
#else  /* BLE-GATT */
//===================================================================================================================
//===================================================================================================================
static ble_gap_callback_t ble_gap_callback[BLE_GATT_MAX_ROLE] = { NULL };
void ble_gap_register_callback(ble_gap_callback_t cb, ble_gatt_role_t event) 
{
    if (cb) {
        ble_gap_callback[event] = cb;
    }
}

void ble_gap_unregister_callback(ble_gatt_role_t event) 
{
    ble_gap_callback[event] = NULL;
}

static void ble_gap_event_callback(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    for (uint8_t i = 0; i < BLE_GATT_MAX_ROLE; i++) {
        if (ble_gap_callback[i])  {
            ble_gap_callback[i](event, param);
        }
    }
}
#endif
//===================================================================================================================
//===================================================================================================================

void bluedroid_stack_deinit(void)
{
    #ifdef TAG
    ESP_LOGI(TAG, "Stop bluetooth...");
    #endif
    // vTaskDelay(200); // BT_APPL: bta_dm_disable BTA_DISABLE_DELAY set to 200 ms
    ESP_ERROR_CHECK( esp_bluedroid_disable() );
    ESP_ERROR_CHECK( esp_bluedroid_deinit() );
    ESP_ERROR_CHECK( esp_bt_controller_disable() );
    ESP_ERROR_CHECK( esp_bt_controller_deinit() );
    return;
}
 
esp_err_t bluedroid_stack_init(void)
{
    esp_log_level_set("BT_INIT", ESP_LOG_WARN);
    esp_log_level_set("BLE_INIT", ESP_LOG_WARN);
    
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();

    ESP_ERROR_CHECK( esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT) );
 
    ESP_ERROR_CHECK( esp_bt_controller_init(&bt_cfg) );
     
    ESP_ERROR_CHECK( esp_bt_controller_enable(ESP_BT_MODE_BLE) );
 
    ESP_ERROR_CHECK( esp_bluedroid_init() );
 
    ESP_ERROR_CHECK( esp_bluedroid_enable() );
 
#if CONFIG_BLE_MESH_ENABLE
    ESP_ERROR_CHECK( esp_ble_mesh_register_ble_callback(ble_mesh_event_callback) ); 
#else
    ESP_ERROR_CHECK( esp_ble_gap_register_callback(ble_gap_event_callback) );
#endif

    ESP_ERROR_CHECK( esp_ble_gatt_set_local_mtu(CONFIG_BLE_GATT_LOCAL_MTU) );  
    
    return ESP_OK;
}


